package com.wg.net.server.http;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.wg.net.server.tcp.ITcpServer;
import com.wg.net.NetConfig;
import com.wg.core.utils.SslUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.MultiThreadIoEventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollIoHandler;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioIoHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.util.concurrent.TimeUnit;

/**
 * HTTP服务器实现（基于Netty），支持SSL、可配置线程模型和处理器链
 *
 * @author 少爷123
 */
public class HttpServer implements ITcpServer {
    private static final Log log = LogFactory.get(HttpServer.class);

    /**
     * 事件循环组（boss负责接受连接，worker负责处理IO）
     */
    private final EventLoopGroup bossGroup;
    private final EventLoopGroup workerGroup;
    /**
     * 服务器启动引导器
     */
    private final ServerBootstrap bootstrap;
    /**
     * 网络配置
     */
    private final NetConfig netConfig;
    /**
     * SSL上下文（如果启用SSL）
     */
    private final SSLContext sslContext;
    /**
     * 服务端Channel
     */
    private Channel serverChannel;
    /**
     * 服务器启动状态标志
     */
    private volatile boolean isStarted = false;

    public HttpServer(NetConfig netConfig) throws Exception {
        this.netConfig = netConfig;
        this.sslContext = createSslContextIfNeeded();

        this.bootstrap = new ServerBootstrap();

        if (Epoll.isAvailable()) {
            this.bossGroup = new MultiThreadIoEventLoopGroup(2, EpollIoHandler.newFactory());
            this.workerGroup = new MultiThreadIoEventLoopGroup(netConfig.getWorkThreads(), EpollIoHandler.newFactory());
            this.bootstrap.group(bossGroup, workerGroup) .channel(EpollServerSocketChannel.class);
        } else {
            this.bossGroup = new MultiThreadIoEventLoopGroup(2, NioIoHandler.newFactory());
            this.workerGroup = new MultiThreadIoEventLoopGroup( netConfig.getWorkThreads(), NioIoHandler.newFactory());
            this.bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class);
        }

        configureBootstrap();
    }

    /**
     * 创建SSL上下文
     */
    private SSLContext createSslContextIfNeeded() throws Exception {
        if (netConfig.isSsl()) {
            log.info("初始化SSL上下文，证书文件: {}, 私钥文件: {}",
                    netConfig.getSslFileName(), netConfig.getSslPrivateKey());
            return SslUtil.createSslContext(netConfig.getSslFileName(), netConfig.getSslPrivateKey());
        }
        return null;
    }

    /**
     * 配置ServerBootstrap（通道类型、处理器链、选项等）
     */
    private void configureBootstrap() {
        bootstrap.option(ChannelOption.SO_BACKLOG, netConfig.getBacklogSize());
        bootstrap.option(ChannelOption.SO_REUSEADDR, netConfig.isReuseAddr());
        bootstrap.option(ChannelOption.SO_KEEPALIVE, netConfig.isKeepAlive());
        bootstrap.option(ChannelOption.TCP_NODELAY, netConfig.isTcpNoDelay());

        bootstrap.childOption(ChannelOption.SO_KEEPALIVE, netConfig.isChildKeepAlive());
        bootstrap.childOption(ChannelOption.TCP_NODELAY, netConfig.isChildTcpNoDelay());

        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) {
                ChannelPipeline pipeline = ch.pipeline();

                if (sslContext != null) {
                    addSslHandler(pipeline);
                }

                // 添加HTTP编解码器
                pipeline.addLast(new HttpServerCodec());

                // 聚合HTTP消息（支持完整HTTP请求处理）
                pipeline.addLast(new HttpObjectAggregator(netConfig.getMaxContentLength()));

                // 支持分块写（如文件上传）
                if (netConfig.isChunkedWriteEnabled()) {
                    pipeline.addLast(new ChunkedWriteHandler());
                }

                // 读取超时处理
                pipeline.addLast(new ReadTimeoutHandler(netConfig.getReadTimeout(), TimeUnit.SECONDS));

                // HTTP请求处理器（核心业务逻辑）
                pipeline.addLast(new HttpServerHandler());

                // 添加自定义处理器
                addCustomHandlers(pipeline);
            }
        });
    }

    /**
     * 添加SSL处理器到管道
     */
    private void addSslHandler(ChannelPipeline pipeline) {
        SSLEngine engine = sslContext.createSSLEngine();
        engine.setUseClientMode(false); // 服务器模式
        engine.setNeedClientAuth(netConfig.isSslClientAuth()); // 是否需要客户端认证
        pipeline.addFirst("ssl", new SslHandler(engine));
        log.debug("SSL处理器已添加");
    }

    /**
     * 添加自定义处理器到管道
     */
    protected void addCustomHandlers(ChannelPipeline pipeline) {
    }

    /**
     * 启动HTTP服务器
     */
    @Override
    public void start() {
        if (isStarted) {
            log.warn("HTTP服务器已启动，无需重复启动");
            return;
        }

        int port = netConfig.getHttpPort();
        if (port <= 0) {
            return;
        }

        log.info("启动HTTP服务器，端口: {}, SSL启用: {}", port, netConfig.isSsl());

        try {
            serverChannel = bootstrap.bind(port).sync().channel();
            log.info("HTTP服务器启动成功，监听端口: {}", port);
        } catch (InterruptedException e) {
            log.error("服务器启动被中断", e);
            Thread.currentThread().interrupt(); // 恢复中断状态
        } catch (Exception e) {
            log.error("服务器启动失败", e);
            throw new RuntimeException("HTTP服务器启动失败", e);
        }
    }

    /**
     * 关闭HTTP服务器（优雅关闭）
     */
    @Override
    public void stop() {
        if (!isStarted) {
            log.warn("HTTP服务器未启动，无需关闭");
            return;
        }

        log.info("开始关闭HTTP服务器...");

        // 关闭服务端Channel（停止接收新连接）
        if (serverChannel != null) {
            log.info("正在关闭服务端Channel...");
            serverChannel.close().addListener(future -> {
                if (future.isSuccess()) {
                    log.info("服务端Channel关闭成功");
                } else {
                    log.error("服务端Channel关闭失败，原因：{}", future.cause());
                }
            });
        }

        // 优雅关闭线程组（停止处理现有连接）
        try {
            // 等待工作线程组关闭完成
            if (workerGroup.shutdownGracefully().await(netConfig.getShutdownTimeout(), TimeUnit.SECONDS)) {
                log.info("工作线程组关闭完成");
            } else {
                log.warn("工作线程组关闭超时，强制终止");
            }

            // 等待Boss线程组关闭完成
            if (bossGroup.shutdownGracefully().await(netConfig.getShutdownTimeout(), TimeUnit.SECONDS)) {
                log.info("Boss线程组关闭完成");
            } else {
                log.warn("Boss线程组关闭超时，强制终止");
            }
        } catch (InterruptedException e) {
            log.error("关闭过程中被中断", e);
            Thread.currentThread().interrupt(); // 恢复中断状态
        } finally {
            log.info("HTTP服务器关闭完成");
        }
    }
}